Kubernetes 核心组件大梳理,看完更明白了
整体资源
的使用状况,部署到任何
地方。先不要扯别的,那会扰乱视线,增加复杂性。任何
这两个字,预示着你并不能够通过常规的IP、端口方式访问部署的实例。复杂性由此而生。我们学k8s,就要看它要调度哪些资源。以传统的感觉来看,无非就是cpu
、内存
、网络
、io
等。在了解怎么对这些资源调度之前,先要搞懂什么叫Pod,这可是k8s的核心概念之一。
搞不懂Pod,就没法玩k8s。
本文的脑图,可以在这里在线查看:http://mind.xjjdog.cn/mind/cloud-k8s
1. Pod
pod是k8s调度的最小单元,包含一个或者多个容器(这里的容器你可以暂时认为是docker)。
Pod拥有一个唯一的IP地址,在包含多个容器的时候,依然是拥有一个IP地址,它是怎么办到的呢?
共享 namespace
,这样 Pod 里的容器就可以通过 localhost 通信了,就像两个进程一样。同理的,Pod 可以挂载多个共享的存储卷(Volume),这时内部的各个容器就可以访问共享的 Volume 进行数据的读写。apiVersion: v1 #本版号
kind: Service #创建的资源类型
metadata: #元数据必选
namespace: bcmall #绑定命名空间
name: bcmall-srv #Service资源名称
spec: #定义详细信息
type: NodePort #类型
selector: #标签选择器
app: container-bcmall-pod
ports: #定义端口
- port: 8080 #port 指定server端口,此端口用于集群内部访问
targetPort: 80 #绑定pod端口
nodePort: 14000 #将server 端口映射到Node节点的端口,用于外网访问
protocol: TCP #端口协议
注意 kind
这个选项,这将是k8s概念膨胀的噩梦!k8s的各种配置,基本上都是围着这里转。哦对了,要让这些yml文件生效,你需要用到kubectl
命令,就像这样。
kubectl create -f ./bcmall.yaml
2. 探针和钩子
常见的有 livenessProbe、readinessProbe、startupProbe 等三种探针。
livenessProbe
有点像心跳
,如果判定不在线了,就会把它干掉;
readinessProbe一般表示就绪
状态,也比较像心跳,证明你的服务在正常跑着;startupProbe用于判断容器是否已经启动好,避免一些超时等,比如你的JVM启动完毕了,才能对外提供服务。
一般,花费120s startupProbe的启动实践,每隔5s检测一下livenessProbe,每隔10s检测一下readinessProbe,是常用的操作。
这些信息,也是在yml中配置的,具体的配置层次如何,这里不罗嗦,您就查文档去吧。
再说一下钩子(Hook)。主要有 PostStart
和 PreStop
两种。PostStart 可以在容器启动之后就执行,PreStop 则在容器被终止之前被执行。这没什么神奇的,就是执行一些shell脚本而已,只不过比较常用,就提升到了关键字的级别。
我们来看看它长什么样子。由于这些配置文件大同小异,后面就不再贴这样的代码了。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: k8s.gcr.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
3. 高可用引起的名词爆炸
上面说到,yaml的复杂性,是由于kind的种类多所引起的。首先我们要接触的,就是 ReplicaSet
。
我们需要多个副本,才能做高可用。
原因很简单,一个Pod就相当于一台机器,当掉之后,就无法提供服务了,这是哪门子的高可用?所以对等的Pod,要有多份才行。
ReplicaSet
简称 RS
,可以让你的Pod数量一直保持在某个水平。但它在操作起来还是有点麻烦了,所以一般使用更加高级的Deployment。Deployment可以实现一些滚动升级的需求,但前提是你需要在spec.template.metadata.labels
中设置了相应的键值对。
k8s的一些过滤工作,都是通过labels来实现的。这其实是一种非常折衷的做法,因为它本身并没有做一些类似于sql查询之类的工作,就只能在这一堆map的键值对上做文章。比如这样:
kubectl get pod -n demo -l app=nginx,version=v1
是不是很魔幻的写法?不要紧,习惯了就好了。
这些yml配置,通常都是一环套一环的,还会有交叉引用,所以也会有优先级。高阶的kind会直接顺带把低阶的kind一起创建了,属于一个级联关系。
一切不过是yml文件包了一层而已。
好了,我们要接触下一个kind:service
了。
为什么需要Service?因为我们上面创建的Pod,哪怕是Deployment
创建的Pod,你访问它都要费些功夫。虽然Pod有IP,但如果它重启了,或者销毁了,IP就会动态变化。因为Pod是被调度的,它并不知道自己会被调度到哪一台机器。
如图所示,通过Labels的过滤,可以把多个Pod归结为一类,然后以某种类型对外暴露服务。Service说白了也是一个组合后的东西。
对外访问的类型,这里要着重说明一下,因为它重要,所以要敲黑板。主要有4种:
ClusterIP 创建一个虚拟的IP,唯一且不可修改。
所有访问该IP的请求,都将被iptables转发到后端。
这是默认的行为,就是一个coredns的插件
NodePort 提供一个静态端口(NodePort)来暴露服务,主要使用的技术是
NAT
LoadBalancer LoadBalancer主要用于做外部的服务发现,即暴露给集群外部的访问
ExternalName 使用较少,感兴趣的可以自行了解
但是等等。k8s是如何实现跨主机的Pod相互访问的呢?
在单个 Node 上的 Pod 相互访问可以理解,直接通过docker0网桥分配的IP,就可相互访问。
那k8s的底层网络是真么设置的呢?答案可能令人沮丧。k8s本身并不负责网络管理,也不为容器提供具体的网络设置,它是通过CNI(容器网络接口)来实现的。在不同的 Node 之上,不同的 Pod 访问就费了点劲,这正是 CNI 的工作。常用的 CNI 插件有:Flannel、Calico、Canal、Weave。
没错,又是一堆名词,而且各个都很难搞。
网络方面是k8s最复杂的知识点,框架也奇多,后面的文章会专门进行介绍。
4. 内部组件
在开启更多的Kind之前,我们来看一下k8s的内部组件。
下面这张图,就是官网的一张图片,说明了k8s的一系列必要的组件。其中,etcd
根本就不是这个体系里的,但k8s的一些持久化状态,需要有个地方存,就引入了这么一个组件,用来存储配置信息。
其中左半部分,是k8s自身的组件;右半部分,就在每个Node(也就是物理机)上的守护进程。它们的作用如下:
kube-apiserver 提供Rest接口,属于k8s的灵魂,所有的认证、授权、访问控制、服务发现等功能,都通过它来暴露
kube-scheduler 一看就是个调度组件,实际上它的作用也是这样。
它会监听未调度的 Pod,实现你指定的目标
kube-controller-manager 负责维护整个k8s集群的状态。
注意是k8s集群的状态,它不管Pod
kubelet 这是个守护进程,用来和apiserver通信,汇报自己Node的状态;
一些调度命令,也是通过kubelet来接收执行任务
kube-proxy kube-proxy其实就是管理service的访问入口,包括集群内Pod到Service的访问和集群外访问service。
这些组件的职责,已经是非常非常清楚了。难点还是在多种Kind概念上。
5. 更多概念
来源:本文转自公众号小姐姐味道,点击查看原文。
XOPS 风向标!GOPS 全球运维大会 2021 · 深圳站,有哪些你最关心互联网议题,猛戳下方视频了解。
近期好文:
线上故障排查全套路,运维小哥可自查~
“高效运维”公众号诚邀广大技术人员投稿,
点击阅读原文,更多精彩